package com.anlu.base.utils;

import com.anlu.base.model.FzTicket;
import com.anlu.base.model.Person;
import com.anlu.base.model.Ret;
import com.anlu.base.model.Student;

import java.util.Date;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * <p>
 * Description:空指针工具
 * <p>
 * <p>
 *
 * @author anlu
 * @date 2024/9/24 10:32
 */
public class NullUtils {


    public static <T,R> NullBO<R> getValue(T bo, Function<T, R> fn){
        if(bo == null){
            return new NullBO<>(null);
        }

        R apply = fn.apply(bo);
        return new NullBO<>(apply);
    }

    public static <T, T1, R> NullBO<R> getValue(T bo,Function<T, T1> fn, Function<T1, R> fn1){
        if (bo == null || fn == null || fn1 == null) {
            return new NullBO<>(null);
        }

        T1 t1 = fn.apply(bo);
        if(t1  == null){
            return new NullBO<>(null);
        }

        R r = fn1.apply(t1);
        return new NullBO<>(r);
    }

    public static <T> String joinString(T bo, String delimiter, Function<T, Object>... fn) {
        StringJoiner joiner = new StringJoiner(Objects.toString(delimiter));
        if (null != bo && null != fn) {
            for (Function<T, Object> f : fn) {
                Object apply = f.apply(bo);
                joiner.add(Objects.toString(apply, ""));
            }
        }
        return joiner.toString();
    }

    public static class NullBO<R>{

        private R bo;

        public NullBO(R bo) {
            this.bo = bo;
        }


        public <RR> RR getIfNull(Supplier<RR>  supplier){
            if(null == bo){
                return supplier.get();
            }
            return null;
        }

        public <RR> RR getIfNotNull(Function<R,RR> fun){
            if(null != bo){
                return fun.apply(get());
            }
            return null;
        }

        public R get() {
            return bo;
        }

        public <RR>RR get(Function<R,RR> fn){
            return fn.apply(get());
        }

        public <RR, U> RR get(BiFunction<R, U, RR> fn, U paramTwo) {
            return fn.apply(get(), paramTwo);
        }

    }

    public static void main(String[] args) {

        Date date = null;

        Long time  =  NullUtils.getValue(date, Date::getTime).get();
        System.out.println(time);


        // test1();

        test2();
    }


    static void test1(){
//        FzTicket pp = new FzTicket();
//        pp.t("121").an(null).bizId("bbb");
//        String s = joinString(pp, "|", FzTicket::getBizId, FzTicket::getAn, FzTicket::getT);
//        System.out.println(s);
//        {
//            FzTicket ppp = null;
//            String value = getValue(ppp, FzTicket::getAn).get();
//            System.out.println("1.1:" + value);
//            value = getValue(pp, FzTicket::getBizId).get();
//            System.out.println("1.2:" + value);
//            value = getValue(pp, FzTicket::getAn).get();
//            System.out.println("1.3:" + value);
//        }
//        {
//            String value = getValue(pp, FzTicket::getTs).get(Objects::toString);
//            System.out.println("2:" + value);
//        }
//        {
//            Ret<FzTicket> ret = Ret.of("c", "m", pp);
//            Object build = NullUtils.getValue(ret, Ret::getData, FzTicket::getAn).get(Objects::toString, "a");
//            System.out.println("3:" + build);
//        }
//        {
//            Ret<FzTicket> ret = Ret.of("c", "m", pp);
//            Object build = NullUtils.getValue(ret, Ret::getData, FzTicket::getAn);
//            System.out.println(build);
//        }

    }

    static void test2(){

//        Student student = Student.builder().age(14).person(Person.builder().years(10).build()).build();
//
//        Object res = NullUtils.getValue(student,Student::getName).get(Objects::toString);
//        System.out.println("res = "+ res);
//
//
//        String result = NullUtils.getValue(student,Student::getPerson, Person::getSex).get(Objects::toString,"aaa");
//        System.out.println("result="+result);
    }
}
